<script setup lang="ts">
  import RouteComponentName from '@/config/route-component-name'
  import { useRoute, useRouter } from 'vue-router'
  import { computed, onMounted, ref } from 'vue'
  import { useFindTemplateById } from '../hooks/useTemplateList'
  import CustomInput from '../form/component-list/CustomInput.vue'
  import CustomTextarea from '../form/component-list/CustomTextarea.vue'
  import CustomRadio from '../form/component-list/CustomRadio.vue'
  import CustomCheckbox from '../form/component-list/CustomCheckbox.vue'
  import CustomSingleSelect from '../form/component-list/CustomSingleSelect.vue'
  import CustomMultipleSelect from '../form/component-list/CustomMultipleSelect.vue'
  import CustomDateTime from '../form/component-list/CustomDateTime.vue'
  import CustomFileUpload from '../form/component-list/CustomFileUpload.vue'
  import CustomAddress from '../form/component-list/CustomAddress.vue'
  import CustomDataConnect from '../form/component-list/custom-data-connect/Index.vue'
  import CustomChildForm from '../form/component-list/CustomChildForm.vue'
  import CustomDivider from '../form/component-list/CustomDivider.vue'
  import { ComponentListItem, ComponentType, DataConnectTable } from '../hooks/types'
  import { FormInstance } from 'element-plus'
  import { useTagsViewStore } from '@/store/modules/tagsView'
  import { useOrderSave, useFindOrderById } from '../hooks/useOrder'

  defineOptions({
    name: RouteComponentName.order.customTemplateInitiateProcess,
  })

  const { template, findLoading, findTemplate } = useFindTemplateById()
  const { form, formSaveLoading, formSave, resetForm } = useOrderSave()
  const { order, findOrderLoading, findOrder } = useFindOrderById()

  const route = useRoute()
  const tagsViewStore = useTagsViewStore()
  const router = useRouter()
  const formInstance = ref<FormInstance | null>(null)
  const componentWidthList = computed(() => {
    const widthMap: Record<ComponentListItem['width'], string> = {
      1: '100%',
      '1/2': '50%',
      '1/3': '33.33%',
      '1/4': '25%',
    }

    return template.value.componentList.map((component) => widthMap[component.width])
  })
  const rules = computed(() => {
    return template.value.componentList.map((item) => {
      if (
        item.required &&
        !item.beControlVisible &&
        !unVisibleComponentIdList.value.includes(item.id)
      ) {
        if (item.type === 'address') {
          return [
            {
              validator: (rule, value, callback) => {
                if (!value.province || !value.city || !value.area || !value.address) {
                  callback(new Error(`${item.label}不能为空`))
                } else {
                  callback()
                }
              },
              trigger: ['change', 'blur'],
            },
          ]
        }

        if (item.type === 'child-form') {
          return [
            {
              validator: (rule, value, callback) => {
                value = value.filter((data) => {
                  let isAllFieldFixed = true
                  for (const key in data) {
                    if (!data[key].isFixed) {
                      isAllFieldFixed = false
                    }
                  }
                  return !isAllFieldFixed
                })
                if (value && value.length <= 0) {
                  callback(new Error(`${item.label}不能为空`))
                  return
                }
                callback()
              },
              trigger: ['change', 'blur'],
            },
          ]
        }

        if (item.type === 'data-connect') {
          return [
            {
              validator: (rule, value, callback) => {
                const componentId = rule.field.split('.')[0]
                if (!form.value[componentId].dataConnectVal) {
                  callback(new Error(`${item.label}不能为空`))
                  return
                }
                callback()
              },
              trigger: ['change', 'blur'],
            },
          ]
        }

        return [{ required: true, message: `${item.label}不能为空`, trigger: ['change', 'blur'] }]
      }

      return []
    })
  })
  const unVisibleComponentIdList = ref<Array<string>>([])
  const flowStartTime = ref(0)
  const loading = computed(
    () => findLoading.value || formSaveLoading.value || findOrderLoading.value,
  )

  const setform = () => {
    template.value.componentList.forEach((component) => {
      form.value[component.id] = {
        inputVal: '',
        textareaVal: '',
        radioVal: '',
        checkboxVal: [],
        singleSelectVal: '',
        dataConnectVal: '',
        multipleSelectVal: [],
        datetimeVal: {
          date: '',
          dateTime: '',
          time: '',
          timeRange: {
            date: '',
            startTime: '',
            endTime: '',
          },
        },
        fileUploadVal: [],
        addressVal: {
          province: '',
          city: '',
          area: '',
          town: '',
          address: '',
        },
        childFormVal: [],
      }
    })
  }

  const init = async () => {
    if (!route.params.id) return

    await findTemplate(route.params.id as string)
    setform()
    flowStartTime.value = new Date().getTime()
    try {
      const orderId = await navigator.clipboard.readText()
      await findOrder(orderId)
    } catch (error) {
      // error
    }
    if (order.value.id) {
      unVisibleComponentIdList.value.length = 0
      form.value = order.value.form
    } else {
      const startNode = template.value.processList[0].nodes.find((node) => node.isStart)
      if (!startNode) {
        return
      }

      unVisibleComponentIdList.value = startNode.fieldPermissions
        .filter((item) => !item.visible)
        .map((item) => item.fieldId)
    }
  }

  const getFormItemProp = (componentItem: ComponentListItem) => {
    const formItemPropMap: Record<ComponentType, Array<string>> = {
      input: [componentItem.id, 'inputVal'],
      textarea: [componentItem.id, 'textareaVal'],
      radio: [componentItem.id, 'radioVal'],
      checkbox: [componentItem.id, 'checkboxVal'],
      'single-select': [componentItem.id, 'singleSelectVal'],
      'multiple-select': [componentItem.id, 'multipleSelectVal'],
      'date-time': [componentItem.id, 'datetimeVal'],
      'file-upload': [componentItem.id, 'fileUploadVal'],
      address: [componentItem.id, 'addressVal'],
      'data-connect': [componentItem.id, 'dataConnectVal'],
      'child-form': [componentItem.id, 'childFormVal'],
      divider: [],
    }

    return formItemPropMap[componentItem.type]
  }

  const onCancelClick = () => {
    tagsViewStore.delView(route.path)
    resetForm()
    router.push('/order/custom/templates')
  }

  const onSaveClick = async () => {
    if (!formInstance.value) {
      return
    }

    try {
      await formInstance.value.validate()
      await formSave(template.value.id)
      onCancelClick()
    } catch (error) {
      // error
    }
  }

  const handleCustomDataConnectChange = (
    component: ComponentListItem,
    selectData: DataConnectTable,
  ) => {
    const data = selectData[0]
    component.dataConnectConfig.fillRules.forEach((item) => {
      if (data && form.value[item.toFieldId] && item.fillMode === 2) {
        form.value[component.id].dataConnectVal = data.id

        const fillComponent = template.value.componentList.find(
          (component) => component.id === item.toFieldId,
        )
        if (fillComponent && !fillComponent.beControlVisible) {
          form.value[item.toFieldId].inputVal = data[item.fromField]
        }
      }
    })
  }

  const handleCustomSingleSelectChange = (component: ComponentListItem, value: string) => {
    component.singleSelectConfig.beControlVisibleRules.forEach((rule) => {
      const componentIndex = template.value.componentList.findIndex(
        (item) => item.id === rule.componentId,
      )
      if (componentIndex === -1) {
        return
      }
      if (rule.optionValue === value) {
        template.value.componentList[componentIndex].beControlVisible = false
      } else {
        template.value.componentList[componentIndex].beControlVisible = true
      }
    })
  }

  onMounted(() => {
    init()
  })
</script>

<template>
  <div v-loading="loading" class="order-custom-template-initiate-process">
    <div class="container">
      <div class="header">
        <div class="title">{{ template.name }}</div>
        <div class="btn-group">
          <h-button type="primary" @click="onSaveClick">保存</h-button>
          <h-button @click="onCancelClick">取消</h-button>
        </div>
      </div>
      <el-form
        ref="formInstance"
        label-position="top"
        class="component-list"
        :model="form"
        inline-message
      >
        <template
          v-for="(component, componentIndex) in template.componentList"
          :key="componentIndex"
        >
          <el-form-item
            v-if="!component.beControlVisible && !unVisibleComponentIdList.includes(component.id)"
            :style="{
              width: component.type === 'divider' ? '100%' : componentWidthList[componentIndex],
            }"
            :label="component.label"
            class="component-item"
            :rules="rules[componentIndex]"
            :prop="getFormItemProp(component)"
          >
            <custom-divider
              v-if="component.type === 'divider'"
              :divider-color="component.dividerConfig.dividerColor"
              :desc="component.dividerConfig.desc"
              :style="component.dividerConfig.style"
              :title="component.dividerConfig.title"
              :title-color="component.dividerConfig.titleColor"
            />
            <custom-input
              v-if="component.type === 'input' && form[component.id]"
              v-model="form[component.id].inputVal"
              :amount-max="component.inputConfig.amountMax"
              :maxlength="component.inputConfig.maxLength"
              :mode="component.inputConfig.mode"
              :number-max="component.inputConfig.numberMax"
              :placeholder="component.inputConfig.placeholder"
            />
            <custom-textarea
              v-if="component.type === 'textarea' && form[component.id]"
              v-model="form[component.id].textareaVal"
              :placeholder="component.textareaConfig.placeholder"
              :maxlength="component.textareaConfig.maxLength"
            />
            <custom-radio
              v-if="component.type === 'radio' && form[component.id]"
              v-model="form[component.id].radioVal"
              :options="component.radioConfig.options"
            />
            <custom-checkbox
              v-if="component.type === 'checkbox' && form[component.id]"
              v-model="form[component.id].checkboxVal"
              :options="component.checkboxConfig.options"
            />
            <custom-single-select
              v-if="component.type === 'single-select' && form[component.id]"
              v-model="form[component.id].singleSelectVal"
              :placeholder="component.singleSelectConfig.placeholder"
              :options="component.singleSelectConfig.options"
              @change="(val: string) => handleCustomSingleSelectChange(component, val)"
            />
            <custom-multiple-select
              v-if="component.type === 'multiple-select' && form[component.id]"
              v-model="form[component.id].multipleSelectVal"
              :placeholder="component.multipleSelectConfig.placeholder"
              :options="component.multipleSelectConfig.options"
            />
            <custom-date-time
              v-if="component.type === 'date-time' && form[component.id]"
              v-model="form[component.id].datetimeVal"
              :placeholder="component.dateTimeConfig.placeholder"
              :datetime-type="component.dateTimeConfig.dateTimeType"
            />
            <custom-file-upload
              v-if="component.type === 'file-upload' && form[component.id]"
              v-model="form[component.id].fileUploadVal"
              :num="component.fileUploadConfig.num"
              :size="component.fileUploadConfig.size"
              :upload-type="component.fileUploadConfig.type"
            />
            <custom-address
              v-if="component.type === 'address' && form[component.id]"
              v-model="form[component.id].addressVal"
            />
            <custom-data-connect
              v-if="component.type === 'data-connect' && form[component.id]"
              :data-type="component.dataConnectConfig.type"
              :field-list="component.dataConnectConfig.fieldList"
              :select-mode="2"
              :field-show-list-after-select="component.dataConnectConfig.showFormFieldList"
              :selected-row-ids="[form[component.id].dataConnectVal]"
              @change="(list: DataConnectTable) => handleCustomDataConnectChange(component, list)"
            />
            <custom-child-form
              v-if="component.type === 'child-form' && form[component.id]"
              v-model="form[component.id].childFormVal"
              :field-list="component.childFormConfig"
            />
          </el-form-item>
        </template>
      </el-form>
    </div>
  </div>
</template>

<style scoped lang="scss">
  .order-custom-template-initiate-process {
    width: 100%;
    height: calc(100vh - 92px);
    padding: 12px;
    box-sizing: border-box;

    .container {
      background-color: #fff;
      width: 100%;
      height: 100%;
      box-sizing: border-box;
      padding: 12px;
      overflow: auto;

      .header {
        display: flex;
        justify-content: space-between;
        align-items: center;

        .title {
          font-size: 16px;
          font-weight: bold;
        }

        .btn-group {
          display: flex;
          justify-content: flex-end;
          column-gap: 8px;
        }
      }

      .component-list {
        display: flex;
        flex-wrap: wrap;
        height: fit-content;

        .component-item {
          box-sizing: border-box;
          padding: 6px;

          :deep(.el-form-item__label) {
            margin: 0;
            font-weight: bold;
            color: #000;
            font-size: 14px !important;
            padding: 5px 0;
          }

          :deep(.el-form-item__content) {
            display: flex;
            flex-direction: column;
            align-items: flex-start;

            .el-form-item__error {
              margin: 0;
            }
          }
        }
      }
    }
  }
</style>
